package com.zb.service.impl;

import com.zb.dto.GenerateParam;
import com.zb.entity.Order;
import com.zb.entity.Tenant;
import com.zb.service.DataGeneratorService;
import com.zb.service.GeneratorStatusService;
import com.zb.service.LogService;
import com.zb.service.OrderService;
import com.zb.service.TenantService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;

@Service
public class DataGeneratorServiceImpl implements DataGeneratorService {

    @Autowired
    private TenantService tenantService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private LogService logService;

    @Autowired
    private GeneratorStatusService statusService;

    @Value("${data-generator.batch-size}")
    private int batchSize;

    @Value("${data-generator.max-threads}")
    private int maxThreads;

    // 订单状态列表
    private static final List<String> ORDER_STATUSES = Arrays.asList(
        "草稿", "待审核", "已审核", "已出库", "车载在途", 
        "已入库", "已库存核算", "已财务核算", "已完成", "红冲"
    );

    // 支付方式列表
    private static final List<String> PAYMENT_METHODS = Arrays.asList(
        "支付宝", "微信支付", "银行转账", "现金", "其他"
    );

    @Async
    @Override
    public Future<Boolean> generateOrderDataAsync(GenerateParam param) {
        try {
            // 标记为正在生成
            statusService.setGenerating(true);
            logService.addLog("开始生成订单数据...");
            logService.addLog("参数: 月份=" + param.getMonths() + 
                             ", 大租户占比=" + param.getBigTenantPercentage() + 
                             "%, 租户数量=" + param.getTenantCount() +
                             ", 每月数据量=" + param.getMonthlyDataVolume() + "万");

            // 1. 创建租户
            logService.addLog("开始创建" + param.getTenantCount() + "个租户...");
            List<Tenant> tenants = tenantService.createTenants(
                param.getTenantCount(), 
                param.getBigTenantPercentage()
            );
            logService.addLog("租户创建完成，共" + tenants.size() + "个租户");

            // 2. 计算每个租户的数据分配比例
            int totalWeight = tenants.stream()
                .mapToInt(Tenant::getDataWeight)
                .sum();

            // 3. 为每个月生成数据
            for (String month : param.getMonths()) {
                logService.addLog("开始生成" + month + "的数据...");
                generateMonthlyData(month, param.getMonthlyDataVolume() * 10000, tenants, totalWeight);
                logService.addLog(month + "的数据生成完成");
            }

            logService.addLog("所有订单数据生成完成！");
            return new AsyncResult<>(true);
        } catch (Exception e) {
            logService.addLog("数据生成失败: " + e.getMessage());
            e.printStackTrace();
            return new AsyncResult<>(false);
        } finally {
            // 重置生成状态
            statusService.setGenerating(false);
        }
    }

    /**
     * 生成指定月份的数据
     */
    private void generateMonthlyData(String yearMonth, int totalCount, List<Tenant> tenants, int totalWeight) {
        // 解析年月
        YearMonth ym = YearMonth.parse(yearMonth, DateTimeFormatter.ofPattern("yyyy-MM"));
        int daysInMonth = ym.lengthOfMonth();
        
        // 创建线程池
        ExecutorService executor = new ThreadPoolExecutor(
            maxThreads,
            maxThreads,
            0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<>(),
            new ThreadPoolExecutor.CallerRunsPolicy()
        );

        try {
            // 为每个租户分配数据量并生成
            List<Future<?>> futures = new ArrayList<>();
            
            for (Tenant tenant : tenants) {
                // 计算该租户应生成的数据量
                long tenantDataCount = (long) (totalCount * (double) tenant.getDataWeight() / totalWeight);
                if (tenantDataCount <= 0) {
                    continue;
                }

                logService.addLog("租户" + tenant.getId() + "(" + tenant.getName() + 
                                 ") 需要生成 " + tenantDataCount + " 条数据");

                // 提交任务
                futures.add(executor.submit(() -> {
                    generateTenantMonthlyData(tenant, yearMonth, daysInMonth, tenantDataCount);
                }));
            }

            // 等待所有任务完成
            for (Future<?> future : futures) {
                try {
                    future.get();
                } catch (Exception e) {
                    logService.addLog("租户数据生成失败: " + e.getMessage());
                }
            }
        } finally {
            executor.shutdown();
        }
    }

    /**
     * 生成指定租户指定月份的数据
     */
    private void generateTenantMonthlyData(Tenant tenant, String yearMonth, int daysInMonth, long totalCount) {
        long generated = 0;
        LocalDateTime now = LocalDateTime.now();
        
        while (generated < totalCount) {
            // 计算当前批次需要生成的数量
            int currentBatchSize = (int) Math.min(batchSize, totalCount - generated);
            List<Order> orders = new ArrayList<>(currentBatchSize);
            
            for (int i = 0; i < currentBatchSize; i++) {
                Order order = new Order();
                
                // 订单ID (雪花ID)
                order.setId(IdUtil.getSnowflake().nextId());
                
                // 租户ID
                order.setTenantId(tenant.getId());
                
                // 订单金额 (0.01 - 100000.00)
                BigDecimal amount = new BigDecimal(RandomUtil.randomDouble(0.01, 100000.00))
                    .setScale(2, BigDecimal.ROUND_HALF_UP);
                order.setAmount(amount);
                
                // 订单日期 (随机分布在当月)
                int day = RandomUtil.randomInt(1, daysInMonth + 1);
                int hour = RandomUtil.randomInt(0, 24);
                int minute = RandomUtil.randomInt(0, 60);
                int second = RandomUtil.randomInt(0, 60);
                
                LocalDateTime orderDate = LocalDateTime.parse(
                    yearMonth + "-" + String.format("%02d", day) + "T" +
                    String.format("%02d", hour) + ":" +
                    String.format("%02d", minute) + ":" +
                    String.format("%02d", second)
                );
                order.setOrderDate(orderDate);
                
                // 创建时间和更新时间
                order.setCreateTime(now);
                order.setUpdateTime(now);
                
                // 订单状态
                order.setStatus(ORDER_STATUSES.get(RandomUtil.randomInt(ORDER_STATUSES.size())));
                
                // 订单编号
                order.setOrderNo("ORD" + DateUtil.format(orderDate, "yyyyMMdd") + 
                                 RandomUtil.randomNumbers(8));
                
                // 客户ID (随机Long)
                order.setCustomerId(RandomUtil.randomLong(1000000, 9999999));
                
                // 产品数量
                order.setProductQuantity(RandomUtil.randomInt(1, 100));
                
                // 支付方式
                order.setPaymentMethod(PAYMENT_METHODS.get(RandomUtil.randomInt(PAYMENT_METHODS.size())));
                
                // 备注
                if (RandomUtil.randomBoolean()) { // 20%概率有备注
                    order.setRemark("Auto-generated order. Tenant: " + tenant.getId());
                }
                
                // 逻辑删除
                order.setDeleted(0);
                
                orders.add(order);
            }
            
            // 保存批次数据
            orderService.batchSaveOrders(orders);
            generated += currentBatchSize;
            
            // 记录进度
            if (generated % (batchSize * 10) == 0 || generated >= totalCount) {
                logService.addLog("租户" + tenant.getId() + " 已生成 " + generated + 
                                 "/" + totalCount + " 条数据");
            }
        }
        
        logService.addLog("租户" + tenant.getId() + " 数据生成完成，共" + generated + "条");
    }
}
